"""
元胞自动机
"""
import copy
import random

import matplotlib.pyplot as plt
import numpy as np


def life_game(length: int = 50, width: int = 50) -> None:
    """_summary_
    生命游戏
    1. 原状态 alive, 周围 alive 细胞数< 2, dies.
    2. 原状态 alive, 周围 alive 细胞 = 2 or 3, lives.
    3. 原状态 alive, 周围 alive 细胞数 > 3, dies.
    4. 原状态 dead, 周围 alive 细胞数 = 3, lives.  

    Args:
        length (int, optional): _description_. Defaults to 50.
        width (int, optional): _description_. Defaults to 50.
    """
    cell = np.zeros((length, width), int)
    cell_temp = copy.deepcopy(cell)
    for i in range(0, length):
        for j in range(0, width):
            cell_temp[i][j] = random.randint(0, 1)

    # 当所有细胞状态不变时结束
    # 可能存在棋盘一直周期性变化，此时如果需要结束可手动结束
    while not(cell_temp == cell).all():
        # 通过读取cell矩阵，不断判断每一个单元格是存活还是死亡，将判断结果保存在cell_temp中，最终再复制给cell矩阵
        cell = copy.deepcopy(cell_temp)
        # 显示每一轮的图像
        plt.imshow(cell)
        plt.pause(0.5)
        # 两重循环遍历整个矩阵，判断每个细胞下一个状态是生存还是死亡
        for i in range(0, length):
            for j in range(0, width):
                '''
                count保存一个细胞周围8个方格内有几个存活的细胞, 注意这两将上下边界和左右边界连接起来进行判断, 
                如对于8*8的棋盘,[0,0]与[0,7]和[7,0]在逻辑上相邻
                '''
                count = cell[(i-1) % length][j]\
                    + cell[(i+1) % length][j]\
                    + cell[i][(j-1) % width]\
                    + cell[i][(j+1) % width]\
                    + cell[(i+1) % length][(j+1) % width]\
                    + cell[(i-1) % length][(j+1) % width]\
                    + cell[(i+1) % length][(j-1) % width]\
                    + cell[(i-1) % length][(j-1) % width]
                # 如果一个单元格是死亡，且周围是三个单元格则存活，否则保持死亡
                if(cell[i][j] == 0 and count != 3):
                    continue
                if(cell[i][j] == 0 and count == 3):
                    cell_temp[i][j] = 1
                    continue
                # 如果一个存活的单元格周围有2或3个单元格存活则该单元格继续存活，否则死亡
                if(count == 2 or count == 3):
                    continue
                cell_temp[i][j] = 0


life_game()
